function out = TrapezeTrainer( InitData ,dataSample, Rules,...
  Params )

	rulesCount = size(Rules,1);
  
  values = zeros(InitData.FeatureCount, 1);
  RulleActivation = zeros(rulesCount, 2);
  
  sigma = InitData.Sigma;
  
  min_error = 100;
  prev_error = 100;
  
  error = 1;
  iter = 0;
  
  max_repeats = 20;
  repeats = 0;
  
  while(error > InitData.MaxError && iter < InitData.MaxEpouch && ...
      repeats < max_repeats)
  
  %Start Epoch
  for i=1: InitData.LearnCount
    for j=1:rulesCount
      for k =1: InitData.FeatureCount
        values(k) = InitData.FuzzySetHandler(dataSample(i,k), Params(Rules(j,k),:,k));
      end%for k
      %[value, index]
      [RulleActivation(j,1),RulleActivation(j,2)] = min(values);
    end%for j
    [~,index] = max(RulleActivation(:,1));
    
    resultClass = Rules(index,end);
    etalonClass = dataSample(i, end);
    
    if(etalonClass ~= resultClass)
      for j=1:rulesCount
%        if (RulleActivation(j,1) > 0)
         
          if (RulleActivation(j,2) ~= etalonClass)
            f = - sigma * RulleActivation(j,1);
          else
            f =  sigma * (1-RulleActivation(j,1));
          end%if
          
          param = Params(Rules(j,RulleActivation(j,2)),:,RulleActivation(j,2));
          x = dataSample(i,RulleActivation(j,2));
          
          if ((x > param(2)) && (x < param(3)))
            
            sigmaA = 0;
            sigmaB = - f * (param(3) - param(2));
            sigmaC =   f * (param(3) - param(2));
            sigmaD = 0;
          else
            
            shift = f * (param(4) - param(1)) * sign(x - param(2));
            
            sigmaA = - f * (param(2) - param(1)) + shift;
            sigmaB = - f * (param(3) - param(2)) + shift;
            sigmaC =   f * (param(3) - param(2)) + shift;
            sigmaD =   f * (param(4) - param(3)) + shift;;            
          end%if
          
          Params(Rules(j,RulleActivation(j,2)),:,RulleActivation(j,2)) = ...
            param + ([sigmaA sigmaB sigmaC sigmaD] / InitData.LearnCount);
%        end%if
      end%for j
    end%if
  end%for i
  %End Epoch
  
  error = 0;
  
  for i=1: InitData.LearnCount
    for j=1:rulesCount
      for k =1: InitData.FeatureCount
        values(k) = InitData.FuzzySetHandler(dataSample(i,k), Params(Rules(j,k),:,k));
      end%for k
      %[value, index]
      [RulleActivation(j,1),RulleActivation(j,2)] = min(values);
    end%for j
    [~,index] = max(RulleActivation);
    
    resultClass = Rules(index,end);
    etalonClass = dataSample(i, end);
    
    if (etalonClass ~= resultClass)
      error = error + 1;
    end
  end %for i
  
  error = error / InitData.LearnCount;
  
  if(min_error > error)
     min_error = error;
    if (InitData.IsSafeState)
     Params_clone = Params;
    end
  end
  
  if (abs(prev_error - error) < 0.0001)
    repeats = repeats + 1;
     if (InitData.IsDynamicStep)
      sigma = sigma + InitData.Sigma;
     end
  else    
    repeats = 0;
    if (InitData.IsDynamicStep)
      sigma = sigma - InitData.Sigma;
     end
  end
  
  prev_error = error;
  
  iter = iter + 1;
%  fprintf('Iteration: %d\tError: %.8f Sigma: %.4f\n', iter, error, sigma);
  end%while
  
  fprintf('Min_error: %.8f\n', min_error);
  fprintf('Error on exit: %.8f\n', error);
  
  if (InitData.IsSafeState)
    Params = Params_clone; 
  end
  
  out = Params;

end

